import com.alibaba.fastjson.JSON
import com.guosen.web.mocker.Collecter
import com.guosen.web.mocker.Handler
import groovy.sql.Sql
import org.slf4j.Logger
import org.slf4j.LoggerFactory

Handler h = (Handler) handler
Logger log = LoggerFactory.getLogger(this.getClass())

h.add('/test') { req, resp ->
    resp.json([list: 1..<20])
}

def p = [
        url   : 'jdbc:h2:/home/mocker/db',
        u     : 'sa',
        p     : '',
        driver: 'org.h2.Driver'
]

h.add('/add') { req, resp ->
    String sys = req.getParameter('sys')
    req.bodyHandler { String body ->
        def db = Sql.newInstance(p.url, p.u, p.p, p.driver)
        db.execute('''
            create table if not exists mocker(
            id int auto_increment primary key,
            sys varchar(20),
            method varchar(20),
            url varchar(200),
            des varchar(200),
            detail varchar(2000),
            dd timestamp
            )
        ''')

        List ll = Collecter.parse(body.readLines())
        log.info('add/update mocker url size - ' + ll.size())
        for (one in ll) {
            def row = db.firstRow('select id from mocker where sys = ? and url = ? and method = ?', [sys, one.url, one.method])
            if (row) {
                db.executeUpdate('delete from mocker where id = ?', [row.id])
                log.info('overwrite ' + one.sys + ' - ' + one.url)
            }
            db.executeInsert('''
                insert into mocker(sys, method, url, des, detail, dd) values(?, ?, ?, ?, ?, ?)
            ''', [sys, one.method, one.url, one.des, JSON.toJSONString(one), new Date()])
        }
        db.close()

        resp.json([flag: true])
    }
}

/*
    mbegin
        method=get
        des=xxx
        url=/mock/test/url
        in:
            age=i+ // 年龄
            amount=f? // 金额
            name=s // 姓名
        out:
            statusCode=i+
            data={}
                ,size=i+
                ,list=[]
                    ,,people={}
                        ,,,name=i+ // 年龄
                        ,,,birth=d+ // 生日
                    ,,class={}
                        ,,,num=i+ // 班级
    mend
 */
h.add('test-mock-real') { req, resp ->
    resp.json([:])
}

h.add('/index') { req, resp ->
    def f = new File('mocker.html')
    def os = resp.getOutputStream()
    os.write(f.exists() ? f.bytes : ''.bytes)
    os.flush()
    os.close()
}

h.add('/del') { req, resp ->
    String id = req.getParameter('id')
    if (!id) {
        return
    }

    def db = Sql.newInstance(p.url, p.u, p.p, p.driver)
    db.executeUpdate('delete from mocker where id = ?', [id])
    db.close()

    resp.json([flag: true])
}

h.add('/query') { req, resp ->
    String q = req.getParameter('q')
    String id = req.getParameter('id')
    if (!q && !id) {
        resp.json([list: []])
        return
    }

    def db = Sql.newInstance(p.url, p.u, p.p, p.driver)
    if (id) {
        Map row = db.firstRow("select * from mocker where id = ?", [id])
        db.close()
        if (!row) {
            resp.json([:])
            return
        }

        Map names = [
                '+': '必填',
                '?': '选填',
                '*': '',
                'i': 'integer',
                'f': 'double',
                'd': 'date',
                's': 'string'
        ]

        Map detail = JSON.parseObject(row.detail)
        String innerInput = detail.input.collect {
            """
<tr>
    <td>${it.key.replaceAll(',', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')}</td>
    <td>${names[it.type] ?: ''}</td>
    <td>${names[it.require] ?: ''}</td>
    <td>${it.des ?: ''}</td>
</tr>
            """
        }.join('')
        String innerOutput = detail.output.collect {
            """
<tr>
    <td>${it.key.replaceAll(',', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')}</td>
    <td>${names[it.type] ?: ''}</td>
    <td>${names[it.require] ?: ''}</td>
    <td>${it.des ?: ''}</td>
</tr>
            """
        }.join('')
        String tbl = """
<tr>
    <td>System/Url</td>
    <td>
    ${row.sys}
<br/>
    ${row.url}
    </td>
</tr>
<tr>
    <td>Description</td>
    <td>${row.des}</td>
</tr>
<tr>
    <td>Input</td>
    <td>
        <table class="table table-striped table-bordered">
            <tr>
                <th>Key</th>
                <th>Type</th>
                <th>Require</th>
                <th>Description</th>
            </tr>
        ${innerInput}
        </table>
    </td>
</tr>
<tr>
    <td>Output</td>
    <td>
        <table class="table table-striped table-bordered">
            <tr>
                <th>Key</th>
                <th>Type</th>
                <th>Require</th>
                <th>Description</th>
            </tr>
        ${innerOutput}
        </table>
    </td>
</tr>
            """
        resp.addHeader('mock-url', row.url.toString())
        def os = resp.getOutputStream()
        os.write(tbl.getBytes('utf-8'))
        os.flush()
        os.close()
    } else {
        List list = db.rows("select * from mocker where url like ?", ['%' + q + '%'])
        db.close()

        list = list.collect {
            '' + it.id + ' -- ' + it.sys + ' -- ' + it.url + ' -- ' + it.des
        }
        resp.json([list: list])
    }
}

h.add('/xmock') { req, resp ->
    String url = req.getAttribute('url')
    if (!url)
        return

    def db = Sql.newInstance(p.url, p.u, p.p, p.driver)
    def row = db.firstRow('select * from mocker where url = ?', [url])
    db.close()
    if (!row) {
        log.info('not found ' + url)
        return
    }

    boolean isShowMeta = req.getParameter('meta') != null
    Map r = JSON.parseObject(row.detail)
    if (isShowMeta) {
        r.sys = row.sys
        resp.json(r)
    } else {
        List list = r.output
        resp.json(Collecter.mockOne(list, list))
    }
}
